package com.aluka.nirvana.framework.security.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONObject;
import com.aluka.nirvana.framework.security.constant.Constants;
import com.aluka.nirvana.framework.security.constant.ResultJsonKey;
import com.aluka.nirvana.framework.security.principal.BaseUserDetails;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * @author gongli
 * @since 2020/4/10 13:32
 */
public class JwtUtils {

    public static final String SIGN_USER = "nirvana";

    public static final String AUTHORITIES = "authorities";

    public static final String IS_ADMIN = "authorities";

    /**
     * 基于用户信息进行 Json Web Token组装
     * @param userDetails 用户信息
     * @param tokenExpireDate token过期时间
     * @return token令牌
     */
    public static String create(BaseUserDetails userDetails , Date tokenExpireDate){

        return Jwts.builder()
                .setId(userDetails.getUserId())
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setIssuer(SIGN_USER)
                .setAudience(String.valueOf(userDetails.isAdmin()))
                .claim(AUTHORITIES, CollectionUtil.join(userDetails.getAuthorities(), ","))
                .setExpiration(tokenExpireDate)
                .signWith(SignatureAlgorithm.HS512, Constants.SIGN_SECRET)
                .compact();

    }
    /**
     * 将响应内容封装至响应体
     * @param response 响应体
     * @param status 响应状态
     * @param message 提示信息
     * @throws IOException 响应失败
     */
    public static void writeResponse(HttpServletResponse response, HttpStatus status, String message) throws IOException {
        JSONObject responseJson = new JSONObject();
        responseJson.put(ResultJsonKey.STATUS, status.value());
        responseJson.put(ResultJsonKey.MSG, message);
        response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(responseJson.toString());
    }

    public static String create(BaseUserDetails userDetails, Date tokenExpireDate, String loginSuccessCustomFields) {
        JwtBuilder jwtBuilder = Jwts.builder()
                .setId(userDetails.getUserId())
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setIssuer(SIGN_USER)
                .setAudience(String.valueOf(userDetails.isAdmin()))
                .claim(AUTHORITIES, CollectionUtil.join(userDetails.getAuthorities(), ","))
                .setExpiration(tokenExpireDate)
                .signWith(SignatureAlgorithm.HS512, Constants.SIGN_SECRET);
        for (String customField : StringUtils.split(loginSuccessCustomFields, ",")) {
            Object customFieldValue = userDetails.getCustomField(customField);
            if(customFieldValue != null){
                jwtBuilder.claim(customField, customFieldValue);
            }
        }
        return jwtBuilder.compact();
    }
}
